﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql.Data.MySqlClient;
using System.Runtime.InteropServices;
using System.Reflection;
using CoreLib.MySQL.Mapping;

namespace CoreLib.MySQL
{
    public class DbInsert : DbBaseQuery<DbInsert>, IDbQuery, IDisposable
    {
        DbProvider dbProvider;
        public DbInsert(DbProvider dbProvider)
        {
            this.dbProvider = dbProvider;
            base.TQuery = this;
        }

        public DbInsert Into(string table)
        {
            base.table = table;
            return this;
        }

        public DbInsert Insert(string column, object value)
        {
            if (value is Enum)
                value = Convert.ToUInt64(value);
            return base.AddParam(column, value);
        }

        public DbInsert Insert<T>(ref T TObject)
        {
            List<DbFieldAttribute> fields = DbMap.GetMap(typeof(T));
            foreach (var field in fields)
            {
                if (field.isProperty)
                {
                    var property = field.memberInClass as PropertyInfo;
                    Insert(field.ColumnName, property.GetValue(TObject, null));
                }
                else
                {
                    var val = field.memberInClass as FieldInfo;
                    Insert(field.ColumnName, val.GetValue(TObject));
                }
            }
            return this;
        }

        public unsafe void Execute()
        {
            using (MySqlCommand cmd = new MySqlCommand())
            {
                StringBuilder queryBuilder = new StringBuilder(string.Format("Insert into {0} (<C>) Values (<V>)", base.table));
#if UNMANAGED
                var columns = base.queryClauses.Select((ptr) => (new string(((QuerySegment*)ptr)->Column)));
                queryBuilder.Replace("<C>", string.Join(",", columns));

                string[] values = new string[base.queryClauses.Count];
                for (int i = 0; i < values.Length; i++)
                {
                    QuerySegment* segment = (QuerySegment*)base.queryClauses.Dequeue();
                    values[i] = base.GetParameter();
                    cmd.Parameters.AddWithValue(values[i], new string(segment->Value));
                    Marshal.FreeHGlobal((IntPtr)segment);
                }
                queryBuilder.Replace("<V>", string.Join(",", values));
#else
                var columns = base.queryClauses.Select((segment) => segment.Column);
                queryBuilder.Replace("<C>", string.Join(",", columns));

                string[] values = new string[base.queryClauses.Count];
                for (int i = 0; i < values.Length; i++)
                {
                    QuerySegment segment = base.queryClauses.Dequeue();
                    values[i] = base.GetParameter();
                    cmd.Parameters.AddWithValue(values[i], segment.Value);
                }
                queryBuilder.Replace("<V>", string.Join(",", values));
#endif

                using (cmd.Connection = dbProvider.CreateDbConnection())
                {
                    cmd.CommandText = queryBuilder.ToString();
                    cmd.ExecuteNonQuery();
                }
            }
        }

        public void Dispose()
        {
            //TODO
        }
    }
}